package com.shhic.hhplt.server.biz;

import com.shhic.hhplt.server.model.WorkbayState;
import com.shhic.hhplt.server.service.IUserService;
import com.shhic.hhplt.testreport.StatusEnum;
import com.shhic.hhplt.testreport.TestReport;
import com.shhic.hhplt.testreport.TestSuiteType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

@Component
@Slf4j
public class WorkbayStateBuffer implements IWorkbayStateBuffer{
	private class WorkbayStateRealtimeState{
		private WorkbayState workbayState = new WorkbayState();	//当前状态
		private Set<String> testedProductIdSet = new HashSet<String>();	//已测过的产品ID集合，用于判断复测
	}
	
	private Map<String,WorkbayStateRealtimeState> workbayStateRealtimeStateMap = new HashMap<String, WorkbayStateBuffer.WorkbayStateRealtimeState>();
	
	@Autowired
	IUserService userService;
	
	private static final int IDLE_WORKBAY_TIMESLOT = 90*60*1000;//工位最大空闲时间，超过即不再关注其状态
	private static final int RECORD_TIMESLOT = 60*60*1000;	//抄表周期
	
	
	/**
	 * 自动抄表的定时任务
	 * @author user
	 *
	 */
	private class AutoRecordTimerTask extends TimerTask {
		@Override
		public void run() {
			log.info("工位情况开始抄表...");
			long recordTime = System.currentTimeMillis();
			List<WorkbayState> wsl = new LinkedList<WorkbayState>();
			synchronized(workbayStateRealtimeStateMap){
				Collection<WorkbayStateRealtimeState> values = workbayStateRealtimeStateMap.values();
				for(WorkbayStateRealtimeState w:values){
					wsl.add(w.workbayState);
				}
			}
			List<String> deadWorkbay = new LinkedList<String>();
			for(WorkbayState w:wsl){
				synchronized(w){
					if(recordTime - w.getUpdateTime()>=IDLE_WORKBAY_TIMESLOT){
						//一个半小时工位无动作，不再记录其状态
						deadWorkbay.add(w.getWorkbayName());
						continue;
					}
					w.setRecordTime(recordTime);
					try{
						userService.saveWorkbayState(w);
					}catch(Exception e){
						e.printStackTrace();
						//其他逻辑不会出错，所以只抓这里
					}
				}
			}
			
			if(!deadWorkbay.isEmpty()){
				synchronized(workbayStateRealtimeStateMap){
					for(String w:deadWorkbay){
						workbayStateRealtimeStateMap.remove(w);
					}
				}
			}
		}
	}
	
	/**
	 * 启动自动抄表定时任务
	 * 从最近的整小时开始，一个小时执行一次
	 */
	@PostConstruct
	public void startAutoRecordThread(){
		//获取第一次执行时间，从当前时间开始，凑个整数的小时数
		Calendar c = Calendar.getInstance();
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		c.add(Calendar.HOUR, 1);	//调试
		Date firstTime = c.getTime();
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new AutoRecordTimerTask(), firstTime,RECORD_TIMESLOT );
		log.info("工位状态抄表任务将在"+c.getTime().toString()+"开始");
	}
	
	
	@Override
	public void notifyWorkbayLogin(String workbay) {
		synchronized(workbayStateRealtimeStateMap){
			WorkbayStateRealtimeState ws = new WorkbayStateRealtimeState();
			ws.workbayState.setLoginTime(System.currentTimeMillis());
			ws.workbayState.setWorkbayName(workbay);
			workbayStateRealtimeStateMap.put(workbay, ws);
		}
	}
	
	@Override
	public List<WorkbayState> getAllRealtimeWorkayState() {
		List<WorkbayState> ws = new LinkedList<WorkbayState>();
		Collection<WorkbayStateRealtimeState> values = workbayStateRealtimeStateMap.values();
		for(WorkbayStateRealtimeState s:values){
			ws.add(s.workbayState);
		}
		return ws;
	}
	
	@Override
	public void notifyTestReport(TestReport uploadedReport) {
		if(uploadedReport.getTestSuite()==null || uploadedReport.getTestSuite().size()==0){
			return;
		}
		String idCode = uploadedReport.getTestingProduct().getIdCode();
		TestSuiteType ts = uploadedReport.getTestSuite().get(0);
		String workbay = ts.getWorkbay();
		synchronized(workbayStateRealtimeStateMap){
			if(!workbayStateRealtimeStateMap.containsKey(workbay)){
				notifyWorkbayLogin(workbay);
			}
		}
		WorkbayStateRealtimeState ws = workbayStateRealtimeStateMap.get(workbay);
		
		synchronized(ws.workbayState){
			if(ws.testedProductIdSet.contains(idCode)){
				ws.workbayState.setRepeat(ws.workbayState.getRepeat()+1);
			}			
			if(ts.getStatus() == StatusEnum.PASS){
				ws.workbayState.setSuccess(ws.workbayState.getSuccess()+1);
			}else{
				ws.workbayState.setFail(ws.workbayState.getFail()+1);
				ws.testedProductIdSet.add(idCode);
			}
			ws.workbayState.setUpdateTime(System.currentTimeMillis());
		}
	}
}
